﻿using System;
using System.Collections.Generic;
using UnityEngine;

namespace Gp.Scripts.Core
{
    [ActionRule("攻击行动")]
    public class AttackAction : AbstractGameAction<AttackActionRequest>
    {
        public override IRuleGroup<AttackActionRequest> BuildRules()
        {
            return GeneralRuleGroup<AttackActionRequest>
                .BindData(InitParameters)
                .AtkRuleChain()
                .Final(CalResult);
        }


        /// <summary>
        /// 初始化数据
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        private static Dictionary<object, ModifierData> InitParameters(AttackActionRequest request)
        {
            var res = new Dictionary<object, ModifierData>
            {
                // 造成的伤害
                [SkillField.Damage] = new(request.Damage),


                // 受击者护甲值
                [SkillField.Defence] = new(0),

                // 伤害减免
                [SkillField.DamageReduce] = new (request.Target.ComStat[StatField.Defence]),

                // 伤害承受
                [SkillField.DamageReceive] = default,

                // 护甲破坏数
                [SkillField.ArmorBreakCount] = new(1),

                // 攻击有效率（默认绝对有效）
                [SkillField.HitRate] = new(1),
            };
            return res;
        }


        #region Cal Result

        /// <summary>
        /// 计算结果。 
        /// </summary>
        /// <param name="request"></param>
        /// <param name="modifies"></param>
        private static IActionResult CalResult(AttackActionRequest request,
            IReadOnlyDictionary<object, ModifierData>              modifies)
        {
            var res = new AttackActionResult(request)
            {
                // 判定攻击是否有效
                IsHit = request.IsHit,

                // ========================== 攻击能力与防御能力比较 =========================
                Blocked = request.DefencePercent > 0,
                // 设置伤害类型
                DamageType = request.DamageType,
                // 单位护甲值
                Defence = modifies[SkillField.Defence].TotalInt(),
                // 设置伤害减免（来源于机制）
                DamageReduce = modifies[SkillField.DamageReduce].TotalInt()
            };

            // 计算失手率
            // if (res.IsHit) res.IsHit = MathUtil.Chance(modifies[SkillField.HitRate].TotalInt());


            // 实际伤害加上攻击目标的受伤加成
            var damage = modifies[SkillField.Damage];
            damage.Add(modifies[SkillField.DamageReceive]);


            // 判定造成的伤害
            // 伤害计算：（总伤害 - 伤害减免） * 伤害比率减免
            res.DamageMake = Mathf.RoundToInt((damage.TotalInt() - res.DamageReduce) * (1 - request.DefencePercent));
            res.DamageMake = Math.Max(0, res.DamageMake);

            // 最终伤害减去护甲防御和伤害减免
            res.HealthDamageMake = Mathf.Max(0, res.DamageMake - res.Defence);

            // int armorBreakCount = modifies[SkillField.ArmorBreakCount].TotalInt();
            //
            //
            // var armorDamage = res.DamageMake;
            //
            // // 是：将伤害完全分配（将护甲视为一块）， 否：不会对未被穿透的护甲造成伤害
            // bool isOverDraftDamage = request.Tags.Contains(SkillTags.Overwhelming);


            // // 计算盾牌伤害
            // var equipHolder = request.Target.ComEquip;
            // // if (!false){
            // foreach (var shield in equipHolder.GetShieldArmors()) {
            //     if (armorDamage <= 0) break;
            //
            //     res.ArmorDamageInfos.Add(new ArmorDamageInfo(shield, armorDamage));
            //
            //     armorDamage -= shield.CurDurability;
            // }
            // // }


            // ===================================== 计算护甲板伤害 ============================================================
            // // 单块护甲板计算模式
            // if (isOverDraftDamage) {
            //     for (int i = 1; i <= equipHolder.ArmorCount(); i++) {
            //         if (armorDamage <= 0) break;
            //
            //         var armor = equipHolder.GetArmor(i);
            //         if (armor == null) break;
            //
            //         res.ArmorDamageInfos.Add(new ArmorDamageInfo(armor, armorDamage));
            //
            //         armorDamage -= armor.CurDurability;
            //     }
            // }
            // else {
            //     // 计算穿透
            //     // 对前n块护甲造成伤害
            //     for (int i = 1; i <= armorBreakCount; i++) {
            //         if (armorDamage <= 0) break;
            //
            //         var armor = equipHolder.GetArmor(i);
            //         if (armor == null) break;
            //
            //         res.ArmorDamageInfos.Add(new ArmorDamageInfo(armor, armorDamage));
            //     }
            // }

            return res;
        }

        #endregion
    }
}